package pl.edu.agh.student.janikhankus;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;

import pl.edu.agh.student.janikhankus.exceptions.BadProbabilitySumException;
import pl.edu.agh.student.janikhankus.exceptions.DuplicatedProductionsException;
import pl.edu.agh.student.janikhankus.exceptions.ParsingException;
import pl.edu.agh.student.janikhankus.grammar.GrammarChecker;
import pl.edu.agh.student.janikhankus.grammar.GrammarLexer;
import pl.edu.agh.student.janikhankus.grammar.GrammarParser;
import pl.edu.agh.student.janikhankus.tree.Grammar;
import pl.edu.agh.student.janikhankus.tree.GrammarTreeCreator;

/**
 * Class which is responsible for calling ANTLR parser and checking grammar semantic.
 * 
 * @author Jaroslaw Janik
 */
public class GrammarLexPar extends Thread {
	
	private String grammarString;
	private Grammar grammar;
	
	/**
	 * Constructor which takes path to grammar file
	 * 
	 * @param grammarString Grammar path as string
	 */
	public GrammarLexPar(String grammarString) {
		this.grammarString = grammarString;
	}
	
	/**
	 * Calls ANTLR parser and lexer, checks grammar semantic and prepares grammar to further actions.
	 * 
	 * @throws ParsingException
	 * @throws BadProbabilitySumException
	 * @throws DuplicatedProductionsException
	 */
	public void work() throws ParsingException, BadProbabilitySumException, DuplicatedProductionsException {
        GrammarLexer lex = new GrammarLexer(new ANTLRStringStream(grammarString));
        CommonTokenStream tokens = new CommonTokenStream(lex);
 
        GrammarParser parser = new GrammarParser(tokens);
 
        try {
	        parser.productions();
	        
	        GrammarChecker grammarChecker = new GrammarChecker();
	        
	        GrammarTreeCreator grammarTreeCreator = new GrammarTreeCreator();
	        grammar = grammarTreeCreator.createGrammarTree(parser.getTokenNames(), tokens);
	        
	        grammarChecker.checkSemantic(grammar);
	        
	        grammarChecker.addTemporaryProductions(grammar);    
        } catch (RecognitionException re) {
        	throw new ParsingException(parser.getErrorHeader(re) + parser.getErrorMessage(re, parser.getTokenNames()));
        }
    }
	
	/**
	 * Returns grammar.
	 * 
	 * @return Grammar
	 */
	public Grammar getGrammar() {
		return grammar;
	}
}